package obs

import (
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
	"github.com/pkg/errors"
	"io"
	"log"
	"math"
	"os"
	"strings"
	"testing"
)

const (
	AK       = "MZL7KMIM3OPEFLYEP6D3"
	SK       = "uY4N6VQSd9sROVMRnSERsGrhaF4auDaeXAC02Nzq"
	EndPoint = "obs.cn-south-1.myhuaweicloud.com"
)

var client, _ = obs.New(AK, SK, EndPoint)

func TestObs(t *testing.T) {
	output, err := client.ListBuckets(nil)
	if err != nil {
		t.Log(err)
		return
	}
	fmt.Println(output.RequestId)
	fmt.Println(output.Owner)
	for index, val := range output.Buckets {
		fmt.Printf("Bucket[%d]-Name:%s,CreationDate:%s\n", index, val.Name, val.CreationDate)
	}
}

func TestListObject(t *testing.T) {
	input := &obs.ListObjectsInput{
		Bucket: "obs-go-thanos",
	}
	input.Prefix = ""
	input.Delimiter = DirDelim
	output, err := client.ListObjects(input)
	if err != nil {
		t.Log(err)
		return
	}
	//fmt.Println(output.CommonPrefixes)
	for _, content := range output.Contents {
		fmt.Println(content.Key)
	}

	for _, dir := range output.CommonPrefixes {
		fmt.Println(dir)
	}
}

func TestPutObject(t *testing.T) {
	input := &obs.PutObjectInput{}
	input.Bucket = "obs-go-thanos"
	input.Key = "text"
	input.Body = strings.NewReader("testdata")
	output, err := client.PutObject(input)
	if err != nil {
		t.Log(err)
		return
	}
	fmt.Println(output)
}

func TestPutDir(t *testing.T) {
	input := &obs.PutObjectInput{}
	input.Bucket = "obs-go-thanos"
	input.Key = "testDir/"
	output, err := client.PutObject(input)
	if err != nil {
		t.Log(err)
		return
	}
	fmt.Println(output)
}

func TestPutFile(t *testing.T) {
	input := &obs.PutObjectInput{}
	input.Bucket = "obs-go-thanos"
	input.Key = "file"
	fd, err := os.Open("D:\\pic\\架构参考图-loki.webp")
	if err != nil {
		t.Log(err)
	}
	input.Body = fd
	output, err := client.PutObject(input)
	if err != nil {
		t.Log(err)
		return
	}
	fmt.Println(output)
}

func TestExist(t *testing.T) {
	input := &obs.GetObjectMetadataInput{}
	input.Bucket = "obs-go-thanos"
	input.Key = "test1"
	output, err := client.GetObjectMetadata(input)
	if err != nil {
		t.Log(err)
	}
	fmt.Println(output)
}

func TestGetObject(t *testing.T) {
	input := &obs.GetObjectInput{}
	input.Bucket = "obs-go-thanos"
	input.Key = "test1"
	output, err := client.GetObject(input)
	if err != nil {
		log.Println(errors.Wrapf(err, ""))
		//t.Log(errors.WithStack(err))
	}
	fmt.Println(output)
}

func TestPutMultiFile(t *testing.T) {
	fileName := "C:\\Users\\Administrator\\Downloads\\Kubernetes in Action中文版 (Marko Luksa) (z-lib.org).pdf"
	bucket := "obs-go-thanos"
	key := "test.pdf"

	inputInit := &obs.InitiateMultipartUploadInput{}
	inputInit.Bucket = bucket
	inputInit.Key = key
	outputInit, err := client.InitiateMultipartUpload(inputInit)
	if err != nil {
		t.Log(errors.Wrap(err, "fail to init multipart upload job"))
	}
	uploadId := outputInit.UploadId
	fileInfo, _ := os.Stat(fileName)
	size := fileInfo.Size()
	partSum, lastPart := int(math.Floor(float64(size)/float64(PartSize))), size%PartSize
	parts := make([]obs.Part, 0, partSum)
	//Todo concurrent way
	for i := 0; i < partSum; i++ {
		inputPart := &obs.UploadPartInput{
			Bucket:     bucket,
			Key:        key,
			UploadId:   uploadId,
			SourceFile: fileName,
			PartNumber: i + 1,
			PartSize:   PartSize,
			Offset:     int64(i) * PartSize,
		}
		output, err := client.UploadPart(inputPart)
		if err != nil {
			t.Log(errors.Wrap(err, "fail to multipart upload"))
		}
		parts = append(parts, obs.Part{PartNumber: output.PartNumber, ETag: output.ETag})
	}
	if lastPart != 0 {
		inputPart := &obs.UploadPartInput{
			Bucket:     bucket,
			Key:        key,
			UploadId:   uploadId,
			SourceFile: fileName,
			PartNumber: partSum + 1,
			//PartSize:   lastPart,
			Offset: int64(partSum) * PartSize,
		}
		output, err := client.UploadPart(inputPart)
		if err != nil {
			t.Log(errors.Wrap(err, "fail to multipart upload"))
		}
		parts = append(parts, obs.Part{PartNumber: output.PartNumber, ETag: output.ETag})
	}
	inputComplete := &obs.CompleteMultipartUploadInput{
		Bucket:   bucket,
		Key:      key,
		UploadId: uploadId,
		Parts:    parts,
	}
	output, err := client.CompleteMultipartUpload(inputComplete)
	if err != nil {
		t.Log(errors.Wrap(err, "fail to complete multipart upload"))
	}
	fmt.Println(output)
}

func TestRange(t *testing.T) {
	bucket := "obs-go-thanos"
	name := "text"
	off := 3
	length := -1
	if strings.TrimSpace(name) == "" {
		t.Log(errors.New("object name cannot be empty"))
	}
	input := &obs.GetObjectInput{}
	input.Bucket = bucket
	input.Key = name
	if off < 0 {
		t.Log(errors.New("incorrect range"))
	}
	input.RangeStart = int64(off)
	if length != -1 {
		input.RangeEnd = int64(off + length - 1)
	} else {
		input.RangeEnd = math.MaxInt64
	}

	output, err := client.GetObject(input)
	if err != nil {
		t.Log(errors.Wrap(err, "fail to get object"))
	}
	content, err := io.ReadAll(output.Body)
	fmt.Println(string(content))
}
